#include <stdio.h>
#include <inttypes.h>

//#a直接得到字符串
//sizeof可以获取变量在内存的空间。
#define MACRO_PRINT_COM(a) printf(#a "=%d, len=%d\n", (int)a, (int)sizeof(a));

int main()
{
    //char类型大小是1字节。
    char ct = 130;
    MACRO_PRINT_COM(ct);//-126，超界变负数。
    unsigned char uct= 130;
    MACRO_PRINT_COM(uct);//宏替换：printf("uct" "=%d, len=%d\n", uct, (int)sizeof(uct));
    //short类型大小是2字节。
    short st = 1;
    MACRO_PRINT_COM(st);
    unsigned short ust = 1;
    MACRO_PRINT_COM(ust);
    //int类型大小是4字节。
    const int it = 1;//常量修饰，it不能修改
    //it = 2;编译失败。常量不允许修改。
    MACRO_PRINT_COM(it);
    volatile unsigned int uit = 1;//易变修饰，每次读取都会读取真实内容，不会被优化。没有volatile修饰情况下，如果多线程改变此变量，主线程while(uit);就永远跳不出去了。
    MACRO_PRINT_COM(uit);
    unsigned uit1 = 1;
    MACRO_PRINT_COM(uit1);
    //long类型大小根据系统来定，32位系统长度为4，64位系统为8字节。
    long lt = 1;//long随系统变化而变化，32位系统为4字节，64位系统为8字节。
    MACRO_PRINT_COM(lt);
    unsigned long ult = 1;
    MACRO_PRINT_COM(ult);
    //long long类型大小是8字节。
    long long llt = 1;
    MACRO_PRINT_COM(llt);
    unsigned long long ullt = 1;
    MACRO_PRINT_COM(ullt);
    float ft = 1.0f;
    printf("ft=%f, len=%d\n", ft, (int)sizeof(ft));
    double dt = 2;
    printf("dt=%f, len=%d\n", dt, (int)sizeof(dt));

    // typedef signed char __int8_t;
    // typedef unsigned char __uint8_t;
    // typedef signed short int __int16_t;
    // typedef unsigned short int __uint16_t;
    // typedef signed int __int32_t;
    // typedef unsigned int __uint32_t;
    // #if __WORDSIZE == 64
    // typedef signed long int __int64_t;
    // typedef unsigned long int __uint64_t;
    // #else
    // __extension__ typedef signed long long int __int64_t;
    // __extension__ typedef unsigned long long int __uint64_t;
    // #endif
    //需要添加头文件：#include <inttypes.h>
    int8_t i8t = 1;//以下类型是平台移植性高。
    MACRO_PRINT_COM(i8t);
    uint8_t u8t = 1;
    MACRO_PRINT_COM(u8t);
    int16_t i16t = 1;
    MACRO_PRINT_COM(i16t);
    uint16_t u16t = 1;
    MACRO_PRINT_COM(u16t);
    int32_t i32t = 1;
    MACRO_PRINT_COM(i32t);
    uint32_t u32t = 1;
    MACRO_PRINT_COM(u32t);
    int64_t i64t = 1;
    MACRO_PRINT_COM(i64t);
    uint64_t u64t = 1;
    MACRO_PRINT_COM(u64t);

    const int intb = 2;
    // intb = 3;因为
    MACRO_PRINT_COM(intb);

    //指针变量/常量大小也随系统大小来定，32位4字节，64位8字节。
    //数组用sizeof是内容的大小，而指针的sizeof是变量本身的大小。
    //数组类型，buf1是常量，他指向的内容是栈区变量。
    char buf1[10] = {0};//备注：0和'0'不一样，取查看ASCII表。
    MACRO_PRINT_COM(buf1[1]);
    unsigned char buf2[] = {'1', '2', '3', '\0'};//'1'表示1字节，"123"表示数组
    printf("buf2 = %s", buf2);//这里也要说明以下，没有\n，终端不会显示，会等到下一个\n或者超出打印缓存区，或使用reflash。
    //const修饰buf3的内容，buf3内容是不可以变的。而buf3是变量，放在栈区。
    const char *buf3 = "12";//const修饰指针内容12，不能改，但buf3可以只想其他指针。这里"12"在常量区
    printf("buf3 = %s\n", buf3);//'\n'为换行符，看ASCII表
    buf3 = buf1;//这是可以的
    //buf3[0] = '0';//这是不行的
    char *buf4 = "3";//这里编译会提示警告，将const char *转为了char *。因为buf4是可以改变内容的。"3"是const类型。你去修改buf4[0]会崩溃。
    printf("buf3 = %s\n", buf4);
    //buf4[0] = '1';//因为buf4指向的是常量区，赋值导致崩溃。
    char * const buf5 = "234";//buf1; //const修饰buf5
    printf("buf5 = %s\n", buf5);
    //buf5 = buf4;不可以
    //buf5[0] = '2';//本身是可以的，但是这里是不行的，因为"234"地址在常量区，修改会崩溃。buf5=buf1,就没问题。
    const char * const buf6 = "354";//自己悟。
    printf("buf6 = %s\n", buf6);
}

// 输出：
// ct=-126, len=1
// uct=130, len=1
// st=1, len=2
// ust=1, len=2
// it=1, len=4
// uit=1, len=4
// uit1=1, len=4
// lt=1, len=8
// ult=1, len=8
// llt=1, len=8
// ullt=1, len=8
// ft=1.000000, len=4
// dt=2.000000, len=8
// i8t=1, len=1
// u8t=1, len=1
// i16t=1, len=2
// u16t=1, len=2
// i32t=1, len=4
// u32t=1, len=4
// i64t=1, len=8
// u64t=1, len=8
// intb=2, len=4
// buf1[1]=0, len=1
// buf2 = 123buf3 = 12
// buf3 = 3
// buf5 = 234

